import { getMenus } from "@/common";
import Cookies from 'js-cookie'
import { MenuItem, MenuList, MenuMap, UserInfo } from "@/types"
export const USER_INFO = "userInfo";
export const TOKEN = "REACT_ADMIN_TOKEN";
export const MENU = "MENU";
export const VISIBLE = "COMPONENTS_VISIBLE";
export const LAYOUT_MODE = "LAYOUT_MODE";
export const SELECT_MENU_KEY = "SELECT_MENU_KEY";

interface MenuOpenData {
  openKeys: string[]
  selectKey: string[]
  openedMenu: MenuItem[]
}
type Token = string | null | undefined

// 获取默认页面
async function getDefaultMenu(): Promise<MenuOpenData> {
  let openKeys: string[] = [],
    selectKey: string[] = [],
    openedMenu: MenuItem[] = [];
  const menuResult = await getMenus();
  menuResult.data.menus.some((list) => {
    const child = list[MENU_CHILDREN]
    if (child && child.length) {
      openKeys = [(list[MENU_KEY] as string)];
      selectKey = [(child[0][MENU_KEY] as string)];
      openedMenu = [child[0]];
      return true;
    }
    return false;
  });

  return {
    openKeys,
    selectKey,
    openedMenu,
  };
}

function getSessionUser() {
  return getKey(false, USER_INFO);
}

function saveUser(info: UserInfo) {
  setKey(true, USER_INFO, info);
  setKey(false, USER_INFO, info);
}


function sleep(seconed: number) {
  return new Promise((res, rej) => {
    setTimeout(res, seconed);
  });
}

function getLocalUser() {
  return getKey(true, USER_INFO);
}


function getMenuParentKey(list: MenuList, key: string): string[] {
  const keys = [];
  const info = list.find((item) => item[MENU_KEY] === key);
  let parentKey = info?.[MENU_PARENTKEY];
  if (parentKey) {
    const data = getMenuParentKey(list, parentKey)
    keys.push(...data);
    keys.push(parentKey);
  }
  return keys;
}

export function formatMenu(list: MenuList) {
  const newList = list.map(item => ({ ...item }))
  const menuMap: MenuMap = {};
  const parentMenu: MenuList = [];
  newList.forEach((item) => {
    // 当前 菜单的key
    const currentKey = item[MENU_KEY];
    // 当前 菜单的父菜单key
    const currentParentKey = item[MENU_PARENTKEY];
    // 如果 映射表还没有值 就把当前项 赋值进去
    if (!menuMap[currentKey]) {
      menuMap[currentKey] = item;
    } else {
      // 有值 说明 有子项 保留子项 把当前值 赋值进去
      item[MENU_CHILDREN] = menuMap[currentKey][MENU_CHILDREN];
      menuMap[currentKey] = item;
    }
    // 如果当前项 有父级
    if (currentParentKey) {
      // 父级还没有在映射表上
      if (!menuMap[currentParentKey]) {
        // 那就把映射上去 只有子集属性<Array>类型
        menuMap[currentParentKey] = {
          [MENU_CHILDREN]: [item],
        };
      } else if (
        menuMap[currentParentKey] &&
        !menuMap[currentParentKey][MENU_CHILDREN]
      ) {
        // 父级在映射表上 不过 没子集
        menuMap[currentParentKey][MENU_CHILDREN] = [item];
      } else {
        // 父级有 子集合也有
        menuMap[currentParentKey][MENU_CHILDREN]?.push(item);
      }
    } else {
      // 当前项是没有父级 那当前项就是父级项
      parentMenu.push(item);
    }
  });
  return parentMenu;
}

export function setTreeData (arr: MenuList) {
  // 删除所有的children, 以防止多次调用
  if (JSON.stringify(arr) === '{}') {
    return
  }
  arr.forEach(function (item) {
    delete item.children
  })
  const map:any = {} // 构建map
  arr.forEach(i => {
    map[i.uuid] = i // 构建以id为键 当前数据为值
  })
  const treeData: MenuItem[] = []
  arr.forEach(child => {
    const mapItem = map[child.parent_id] // 判断当前数据的parentId是否存在map中
    if (mapItem) {
      // 存在则表示当前数据不是最顶层的数据
      // 注意： 这里的map中的数据是引用了arr的它的指向还是arr,当mapItem改变时arr也会改变，踩坑点
      (mapItem.children || (mapItem.children = [])).push(child) // 这里判断mapItem中是否存在child
    } else {
      // 不存在则是顶层数据
      treeData.push(child)
    }
  })
  return treeData
}

function reduceMenuList(list: MenuList, path: string = ''): MenuList {
  const data: MenuList = [];
  list.forEach((i) => {
    const { children, ...item } = i;
    item.parentPath = path;
    if (children) {
      const childList = reduceMenuList(children, path + i.path);
      data.push(...childList);
    }
    data.push(item);
  });
  return data;
}

function getLocalMenu(): MenuList | null {
  return getKey(false, MENU);
}

function saveLocalMenu(list: MenuList) {
  setKey(false, MENU, list);
}

function getLocalSelectMenuKey(): string[] | null {  
  return getKey(true, SELECT_MENU_KEY);
}

function saveLocalSelectMenuKey(array: string[]) {
  setKey(true, SELECT_MENU_KEY, array);
}

function saveToken(token: Token) {
  setKey(true, TOKEN, token)
}

function getToken(): Token {
  return getKey(true, TOKEN)
}

function getKey(isLocal: boolean, key: string) {
  return JSON.parse(getStorage(isLocal).getItem(key) || "null");
}
function getStorage(isLocal: boolean) {
  return isLocal ? window.localStorage : window.sessionStorage;
}
function setKey(isLocal: boolean, key: string, data: any) {
  getStorage(isLocal).setItem(key, JSON.stringify(data || null));
}

function rmKey(isLocal: boolean, key: string) {
  getStorage(isLocal).removeItem(key);
}

function stopPropagation(e: MouseEvent) {
  e.stopPropagation();
}

function clearLocalDatas(keys: string[]) {
  sessionStorage.clear()
  localStorage.clear()
  Cookies.remove('applyList')
  Cookies.remove('username')
  Cookies.remove('userId')
  Cookies.remove('tenants')
  Cookies.remove('getTokenTime')
  keys.forEach((key) => {
    rmKey(true, key);
    rmKey(false, key);
  });
}

function getDefaultSelectMenuKey(list:MenuList, keys: string[]|null){
  let key:string[] = [];
  if(keys&&keys.length>0){
    list.forEach((item) => {
      if(item[MENU_CHILDREN]){
        key=[...key, ...getDefaultSelectMenuKey(item[MENU_CHILDREN], keys)]
      }else if(item[MENU_KEY]==keys[0]){
        key.push(String(item[MENU_KEY]))
      }
    })
  }else{
    key=[String(list[0]['uuid'])]
  }
  return key
}

export {
  getDefaultMenu,
  getSessionUser,
  sleep,
  getLocalUser,
  getMenuParentKey,
  reduceMenuList,
  getLocalMenu,
  saveLocalMenu,
  saveToken,
  getToken,
  getKey,
  setKey,
  rmKey,
  stopPropagation,
  clearLocalDatas,
  saveUser,
  getLocalSelectMenuKey,
  saveLocalSelectMenuKey,
  getDefaultSelectMenuKey
};
